package algorithm;

import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import com.robot.common.api.CurrentUserSupport;

import com.alibaba.fastjson.JSONObject;
import com.robot.dao.dto.CreateRobotResultDTO;
import com.robot.dao.dto.SendMessageDTO;
import com.google.gson.Gson;
import com.robot.dao.feigndto.actionunitdto.*;
import com.robot.common.client.HttpClient;
import com.robot.dao.feigndto.chatdto.ChatTextStreamRequest;
import com.robot.dao.feigndto.chatdto.ExcelStreamRequest;
import com.robot.dao.feigndto.chatdto.PictureStreamRequest;
import com.robot.dao.feigndto.context.RequestContext;
import com.robot.dao.feigndto.ragdto.FileDeleteRequest;
import com.robot.dao.feigndto.ragdto.ParsingApiResponse;
import com.robot.dao.feigndto.ragdto.ParsingRequest;
import com.robot.dao.feigndto.robotdto.AgentCreate;

import com.robot.dao.feigndto.robotdto.AgentCreateByFiles;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Flux;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.util.List;

@Component
public class AlgorithmCaller{
    //  private static final String BASE_URL = "http://121.199.66.169:9000";
    private static final String BASE_URL = "http://47.96.231.221:9000";
    private static final String BASE_URL_WITH_COMPONENT = BASE_URL+"/component";
    @Autowired
    private WebClient webClient;

    public String test(){
        return "test finish";
    }

    // 组件功能执行
    public CompletableFuture<Object> handleTask(SendMessageDTO sendMessageDTO, List<String> fileIdList, String action, ThreadPoolExecutor threadPoolExecutor
    ) {
        CompletableFuture<Object> res =CompletableFuture.supplyAsync(() -> {
            Gson gson = new Gson();
            RecallResearchRequest input = new RecallResearchRequest().builder()
                    .action(action)
                    .config(new RecallResearchInputConfig(5))
                    .input(new RecallResearchInputData(sendMessageDTO.getMessage(), fileIdList))
                    .account_id(getAccountId())
                    .build();
            System.out.println("run there = 2");
            Map<String, Object> headerMap = new HashMap<>();
            headerMap.put("Content-Type", "application/json");
            headerMap.put("Accept", "application/json");
            String result = HttpClient.doPostForObject(BASE_URL_WITH_COMPONENT, headerMap, input, Charset.forName("UTF-8"));
            return gson.fromJson(result, RecallApiResponse.class);
        }, threadPoolExecutor);
        return res;
    }
    
    // echats对话
    public Flux<String> echartsChat(ExcelStreamRequest excelStreamRequest) {
        Gson gson = new Gson();
        excelStreamRequest.setAccount_id(getAccountId());
        String jsonData = gson.toJson(excelStreamRequest);
        this.webClient = WebClient.builder()
                .baseUrl(BASE_URL)
                .build();
        return webClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/component")
                        .build())
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(jsonData)
                .accept(MediaType.TEXT_EVENT_STREAM)// or MediaType.TEXT_EVENT_STREAM
                .header("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                .header("Connection", "keep-alive")
                .retrieve()
                .bodyToFlux(String.class);
    }


    // 图片对话
    public Flux<String> pictureChat(PictureStreamRequest pictureStreamRequest) {
        Gson gson = new Gson();
        pictureStreamRequest.setAccount_id(getAccountId());
        String jsonData = gson.toJson(pictureStreamRequest);
        this.webClient = WebClient.builder()
                .baseUrl(BASE_URL)
                .build();
        return webClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/component")
                        .build())
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(jsonData)
                .accept(MediaType.TEXT_EVENT_STREAM)// or MediaType.TEXT_EVENT_STREAM
                .header("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                .header("Connection", "keep-alive")
                .retrieve()
                .bodyToFlux(String.class);
    }
    
    // 普通文本对话
    public Flux<String> textChat(String message , ArrayList<String>  embeddingStrs,List<ChatTextStreamRequest.History> historyList,String robotID,String characterDesign) throws Exception {
//        message=message+"。请根据以下角色设定回答："+characterDesign;
        ChatTextStreamRequest chatInput = new ChatTextStreamRequest().builder()
                .action("chat-text-stream")
                .account_id(getAccountId())
                .config(new ChatTextStreamRequest.Config().builder().temperature(0.1).build())
                .robot_id(robotID)
                .input(new ChatTextStreamRequest.Input().builder().character_design(characterDesign).text(message).embedding_strs(embeddingStrs).history(historyList).build())
                .build();

        Gson gson = new Gson();
        String jsonData = gson.toJson(chatInput);
        this.webClient = WebClient.builder()
                .baseUrl(BASE_URL)
                .build();
        return webClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/component")
                        .build())
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(jsonData)
                .accept(MediaType.TEXT_EVENT_STREAM)// or MediaType.TEXT_EVENT_STREAM
                .header("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
                .header("Connection", "keep-alive")
                .retrieve()
                .bodyToFlux(String.class);

    }



    private String getAccountId()  {

        RequestContext.UserAccountInfoCtx userAccountInfo= RequestContext.getUserAccountInfo();
        System.out.println("userAccountInfo="+userAccountInfo);

        return userAccountInfo.getAccountID().toString();
    }
    
    // 算法创建机器人：后端向算法请求后，算法返回机器人的简介、机器人名等配置信息。
    public CreateRobotResultDTO createBySentence(ArrayList<AgentCreate.Knowledge> knowledgeArrayList,String sentence) throws IOException {
        AgentCreate agentCreate = new AgentCreate().builder()
                .input(new AgentCreate.Input().builder()
                        .text(sentence)
                        .knowledge_list(knowledgeArrayList).build())
                .action("cr-agent-by-sentence")
                .account_id(getAccountId())
                .build();
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "application/json");
        System.out.println("[createBySentence]agentCreate="+agentCreate);
        String resString = HttpClient.doPostForObject(BASE_URL_WITH_COMPONENT, headerMap, agentCreate, Charset.forName("UTF-8"));
        System.out.println("[createBySentence]resString="+resString);

        CreateRobotResultDTO createRobotResultDTO =
                JSONObject.parseObject(resString)
                        .getObject("data", JSONObject.class).getObject("output", CreateRobotResultDTO.class);
        return createRobotResultDTO;
    }

    //
    public CreateRobotResultDTO createByFiles(List<String> fileNames2) throws IOException {
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "application/json");

        AgentCreateByFiles agentCreate = new AgentCreateByFiles().builder()
                .input(new AgentCreateByFiles
                        .Input().builder()
                        .file_name_list(fileNames2)
                        .build())
                .action("cr-agent-by-file")
                .account_id(getAccountId())
                .build();
        String resString = HttpClient.doPostForObject(BASE_URL_WITH_COMPONENT, headerMap, agentCreate, Charset.forName("UTF-8"));
        System.out.println("resString="+resString);
        //使用CreateRobotResultDTO接收返回结果
        if (JSONObject.parseObject(resString).getObject("code", Integer.class) != 2000) {
            return null;
        }
        CreateRobotResultDTO createRobotResultDTO =
                JSONObject.parseObject(resString)
                        .getObject("data", JSONObject.class).getObject("output", CreateRobotResultDTO.class);

        return createRobotResultDTO;
    }



    //文件操作：parsing-files-embedding
    public void parsingFilesEmbedding(List<ParsingRequest.File> fileList){
        ParsingRequest fileDeleteRequest = new ParsingRequest().builder()
                .action("parsing-files-embedding")
                .account_id(getAccountId())
                .input(new ParsingRequest.Input().builder()
                        .file_list(fileList)
                        .build())
                .build();
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "application/json");
        String result = HttpClient.doPostForObject(BASE_URL, headerMap, fileDeleteRequest, Charset.forName("UTF-8"));
        Gson gson = new Gson();
        ParsingApiResponse parsingApiResponse = gson.fromJson(result, ParsingApiResponse.class);
        System.out.println("parsingFiles--------调用算法返回的结果{}"+parsingApiResponse.getCode());
    }

    // 文件操作：de-files-content
    public ParsingApiResponse deFilesContent(ArrayList<String> fileList){
        FileDeleteRequest fileDeleteRequest = new FileDeleteRequest().builder()
                .action("de-files-content")
                .account_id(getAccountId())
                .input(new FileDeleteRequest.Input().builder()
                        .file_id_list(fileList)
                        .build())
                .build();
        Gson gson = new Gson();
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "application/json");
        String result = HttpClient.doPostForObject(BASE_URL_WITH_COMPONENT, headerMap, fileDeleteRequest, Charset.forName("UTF-8"));
        ParsingApiResponse parsingApiResponse = gson.fromJson(result, ParsingApiResponse.class);
        return parsingApiResponse;
    }

    // 文件操作：de-files-embedding
    public ParsingApiResponse deFilesEmbedding(Long knowledgeId){
        // 调用算法进行知识库删除
        String fileId = knowledgeId.toString();
        ArrayList<String> fileList = new ArrayList<>();
        fileList.add(fileId);
        Gson gson = new Gson();
        FileDeleteRequest fileDeleteRequest = new FileDeleteRequest().builder()
                .action("de-files-embedding")
                .account_id(getAccountId())
                .input(new FileDeleteRequest.Input().builder()
                        .file_id_list(fileList)
                        .build())
                .build();
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Accept", "application/json");
        String result = HttpClient.doPostForObject(BASE_URL, headerMap, fileDeleteRequest, Charset.forName("UTF-8"));
        ParsingApiResponse parsingApiResponse = gson.fromJson(result, ParsingApiResponse.class);
        System.out.println(parsingApiResponse);
        System.out.println("知识库调用算法的返回结果" + String.valueOf(parsingApiResponse.getCode()));
        return parsingApiResponse;
    }

    public List<String> uploadFileAndGetImages(MultipartFile multipartFile) throws IOException {
        // 创建RestTemplate实例用于发送HTTP请求
        RestTemplate restTemplate = new RestTemplate();

        // 设置请求头，指定内容类型为multipart/form-data，用于上传文件
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        // 创建用于存储form-data数据的MultiValueMap
        MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
        // 将MultipartFile添加到form-data中，参数名设置为"file"，与目标接口要求一致
        formData.add("file", multipartFile.getResource());

        // 创建HttpEntity，将formData和headers封装进去
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, headers);

        // 发送POST请求到目标接口
        ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://4e00513e.r9.cpolar.top/e-commerce", requestEntity, String.class);

        // 获取响应的JSON字符串内容
        String responseBody = responseEntity.getBody();

        // 使用Gson库解析JSON数据，获取"data.images"中的内容（假设响应格式固定如此）
        try {
            Gson gson = new Gson();
            // 通过TypeToken来指定要解析的泛型类型，这里是List<String>
//            TypeToken<List<String>> typeToken = new TypeToken<List<String>>() {};
//            List<String> images = gson.fromJson(responseBody, WorkFlowResp.class);
            WorkFlowResp images = gson.fromJson(responseBody, WorkFlowResp.class);
            return images.data.images;
        } catch (Exception e) {
            System.out.println("fromJson err,responseBody="+responseBody);
            e.printStackTrace();
            // 如果解析出现错误，返回空列表，也可根据业务需求抛出异常等其他处理方式
            return null;
        }
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class WorkFlowResp implements Serializable {
        Long code;
        String message;
        WorkFlowRespData data;
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class WorkFlowRespData implements Serializable {
        List<String> images;
    }
}